<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>注释版本</title>
  </head>
<!-- 本程序主要处理，前端使用echart画折线图的场景，后台数据的纵坐标为空的数据缺失。需要前端自己判断出位置并补充上正常的数据结构才能达到echart图正常渲染的目的 -->
<!-- 例如：这里 x坐标是3个时间，当时每条曲线上后台只给了2个点，另外一个时间点上val为空的值的点没给，需要你补上，看似简单，写了150行+代码来处理 -->
<!-- 每个for只能处理好一件事，有时层层for去内层处理数据，接口一般是到库里拿数据组装一个合适的结构给你，但是echart的数据要求比较 '别致' 不一样，你必须得手动加工处理 -->

<!-- 写过echart 的都懂，这种频繁的数据结构处理，有时借助loash这种工具库，可以达到快速处理数据的目的 -->
  <body>
    test
    <script>
      var notempty = function (arrObj) {
        var arr = [];
        map((item) => {
          if (item.val !== "" && val != undefined) {
            arr.push(item);
          }
        });

        return arr;
      };

      var toTimeStap = function (time) {
        return Date.parse(new Date(time).toString());
      };

      //attr：根据该属性排序；rev：升序1或降序-1，不填则默认为1
      var sortBy = function (attr, rev) {
        if (rev == undefined) {
          rev = 1;
        } else {
          rev ? 1 : -1;
        }
        return function (a, b) {
          a = a[attr];
          b = b[attr];
          if (a < b) {
            return rev * -1;
          }
          if (a > b) {
            return rev * 1;
          }
          return 0;
        };
      };

      var arr = [
        {
          Exam_ExamDataOcr: [
            {
              ExamItemID: "54",
              ExamItemName: "视野检查（中心视野）",
              ExamInfo_ID:
                "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811023116.1",
              ExamBeginDate: "2022-05-29T12:14:37",
              DataOcrValueList: [
                // del 2 dot
                // {
                //   ExamInfo_ID:
                //     "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811023116.1",
                //   Eyes: "OD",
                //   CureName: "MD",
                //   StandardName: "11",
                //   MaxValue: "1.4",
                //   MinValue: "0.1",
                //   DataOcrVaule: "-0.19",
                // },
                // {
                //   ExamInfo_ID:
                //     "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811023116.1",
                //   Eyes: "OD",
                //   CureName: "PSD",
                //   StandardName: "11",
                //   MaxValue: "1.4",
                //   MinValue: "0.1",
                //   DataOcrVaule: "1.15",
                // },
                //add a dot
                {
                  ExamInfo_ID:
                    "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811022304.1",
                  Eyes: "OD",
                  CureName: "MD",
                  StandardName: "11",
                  MaxValue: "1.4",
                  MinValue: "0.1",
                  DataOcrVaule: "0.918",
                },
              ],
            },
            {
              ExamItemID: "54",
              ExamItemName: "视野检查（中心视野）",
              ExamInfo_ID:
                "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811022304.1",
              ExamBeginDate: "2022-05-25T14:52:28",
              DataOcrValueList: [
                // add
                {
                  ExamInfo_ID:
                    "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811022304.1",
                  Eyes: "OD",
                  CureName: "MD",
                  StandardName: "11",
                  MaxValue: "1.4",
                  MinValue: "0.1",
                  DataOcrVaule: "0.917",
                },
                {
                  ExamInfo_ID:
                    "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811022304.1",
                  Eyes: "OD",
                  CureName: "MD",
                  StandardName: "11",
                  MaxValue: "1.4",
                  MinValue: "0.1",
                  DataOcrVaule: "0.14",
                },
                {
                  ExamInfo_ID:
                    "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811022304.1",
                  Eyes: "OD",
                  CureName: "PSD",
                  StandardName: "11",
                  MaxValue: "1.4",
                  MinValue: "0.1",
                  DataOcrVaule: "1.22",
                },
                {
                  ExamInfo_ID:
                    "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811022304.1",
                  Eyes: "OS",
                  CureName: "MD",
                  StandardName: "11",
                  MaxValue: "1.4",
                  MinValue: "0.1",
                  DataOcrVaule: "-0.4",
                },
                {
                  ExamInfo_ID:
                    "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811022304.1",
                  Eyes: "OS",
                  CureName: "PSD",
                  StandardName: "11",
                  MaxValue: "1.4",
                  MinValue: "0.1",
                  DataOcrVaule: "1.26",
                },
              ],
            },
            {
              ExamItemID: "54",
              ExamItemName: "视野检查（中心视野）",
              ExamInfo_ID:
                "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811021320.1",
              ExamBeginDate: "2022-04-24T12:14:37",
              DataOcrValueList: [
                {
                  ExamInfo_ID:
                    "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811021320.1",
                  Eyes: "OS",
                  CureName: "MD",
                  StandardName: "11",
                  MaxValue: "1.4",
                  MinValue: "0.1",
                  DataOcrVaule: "-0.82",
                },
                {
                  ExamInfo_ID:
                    "1.2.276.0.7230010.3.1.2.22095313475612.2684.20220811021320.1",
                  Eyes: "OS",
                  CureName: "PSD",
                  StandardName: "11",
                  MaxValue: "1.4",
                  MinValue: "0.1",
                  DataOcrVaule: "1.49",
                },
              ],
            },
          ],
          Exam_ExamItemID: "'54'",
        },
      ];

      var arr0 = arr[0];
      var Exam_ExamDataOcr = arr0.Exam_ExamDataOcr;

      // Date 是x 上的点， CureName+Eyes 是类别，y 上点事DataOcrValue 一种类型对应一条线。

      //  x 点提取，一层遍历Exam_ExamDataOcr，读取 ExamBeginDate 字段写入 []
      // y 点提取，Exam_ExamDataOcr[i].DataOcrValueList[j].CureName & DataOcrVaule；相同CureName的放到一个数据里。

      var series = [];//echart所要的数据结构
      var xDots = [];//x坐标点，时间
      let namesList = [];//曲线类别，一个类别一条折线
      let uniNameList=[]//提纯nameList类别，重复的剔除掉
      let dotValList = [];//y坐标上点
      let timeDotDict = []; // x  y 做关联的字典对照表。

      // 提取数据
      for (let x = 0; x < Exam_ExamDataOcr.length; x++) {
        let itemx = Exam_ExamDataOcr[x];
        xDots.push(toTimeStap(itemx.ExamBeginDate));

        for (let y = 0; y < itemx.DataOcrValueList.length; y++) {
          let itemy = itemx.DataOcrValueList[y];
          namesList.push(itemy.CureName + itemy.Eyes);
          dotValList.push({
            // 对象动态key值
            [itemy.CureName + itemy.Eyes]: itemy.DataOcrVaule,
            time: toTimeStap(itemx.ExamBeginDate), //time 节点 先转成时间戳
          });

          timeDotDict.push({
            ExamBeginDate: itemx.ExamBeginDate,
            DataOcrVaule: itemy.DataOcrVaule,
          });
        }
      }
      
      
      //类别去重保证唯一性
       uniNameList = Array.from(new Set(namesList));
      console.log(timeDotDict, "timeDotDict");

      // 处理出echart所要的半成品数据，val值和时间做好关联
      for (let z = 0; z < uniNameList.length; z++) {
        let itemz = uniNameList[z];
        let temp = [];

        for (let i = 0; i < dotValList.length; i++) {
          let itemi = dotValList[i];

          temp.push({ val: itemi[itemz], time: itemi.time });
        }

        series.push({
          name: itemz,
          type: "line",
          data: temp,
        });
      }
      console.log(series, "series-source");

      // series里的data去空处理
      series.forEach((item) => {
        var arr = [];
        for (let k = 0; k < item.data.length; k++) {
          if (item.data[k].val !== "" && item.data[k].val != undefined) {
            arr.push(item.data[k]);
          }
        }

        item.data = arr;
      });

      console.log(series, "series", xDots, "x");

      let allIndex = [];//具备的纵坐标个数计数器集合
      let xDotsLen = xDots.length;//x上横坐标点的个数
      // 读取每类曲线上 目前接口数据中所具备的纵坐标点数量。
      series.forEach((itemj, indexJ) => {
        let hasIndex = [];

        itemj.data.forEach((itemz, indexZ) => {
          xDots.forEach((itemi, indexI) => {
            if (itemz.time == itemi) {
              hasIndex.push(indexI);
            }
          });
        });

        allIndex.push(hasIndex);
      });

      // 如果是多个点缺失
      var allNoIndex = [];//通过allIndex 计算出缺失的点数

      allIndex.forEach((item) => {
        let noHasIndex = [];
        if (xDotsLen !== item.length) {
          for (let i = 0; i < xDotsLen; i++) {
            if (item.includes(i) === false) {
              noHasIndex.push(i);
            }
          }
        }
        allNoIndex.push(noHasIndex);
      });

      console.log(JSON.stringify(allNoIndex), "allNoIndex");
      //insert allNoIndex  [2,2,0,0] =>  [[2],[2],[0],[0]]  or [[2,0],[3],[1],[0,1]] 第一类曲线缺失2号 和 0号点，需要插入的。
      // 插入x坐标轴上值为空的点，不然图不出来。
      series.forEach((item, index) => {
        allNoIndex[index].forEach((serialNo, inx) => {
          item.data.splice(serialNo, 0, {
            val: "",
            time: xDots[allNoIndex[index]],
          });
        });
      });

      console.log(series, "series-inserVal");

      // last handle 把 data 按照时间排序，然后把 对象数组 转成 数值数组 投喂给echart折线图
      let result = [];
      series.forEach((item, index) => {
        let temp = [];
        item.data.sort(sortBy("time", 1));
        item.data.forEach((itemi, indexI) => {
          temp.push(itemi.val);
        });
        result.push({
          name: item.name,
          type: "line",
          data: temp,
        });
      });

      console.log(series, "last-series", result);
    </script>
  </body>
</html>
